package com.demon.net

import com.demon.net.converter.CustomGsonConverterFactory
import io.reactivex.schedulers.Schedulers
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.HttpLoggingInterceptor.Logger
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSession
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager

/**
 * 类简要描述
 * <p/>
 * <p>
 * 类详细描述
 * </p>
 *
 * @author zhaozeyang
 * @date 2020/8/25
 */
object RetrofitFactory {

  const val TAG = "Retrofit"

  /**
   * 构建Service
   */
  fun <T> createService(
    clazz: Class<T>,
    domain: String = "",
    interceptors: List<Interceptor>? = null
  ): T {
    val retrofit = Retrofit.Builder()
        .baseUrl(domain)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
        .addConverterFactory(CustomGsonConverterFactory.create())
//        .addConverterFactory(GsonConverterFactory.create())
        .client(createClient(interceptors))
        .build()
    return retrofit.create(clazz)
  }

  fun <T> createService(
    clazz: Class<T>,
    domain: String = "",
    interceptor: Interceptor
  ): T {
    return createService(clazz, domain, mutableListOf(interceptor))
  }

  fun <T> createService(
    clazz: Class<T>,
    domain: String
  ): T {
    val retrofit = Retrofit.Builder()
        .baseUrl(domain)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
        .addConverterFactory(GsonConverterFactory.create())
        .client(createClient())
        .build()

    return retrofit.create(clazz)
  }

  /**
   * 构建协程请求Service
   */
  fun <T> createCoroutineService(
    clazz: Class<T>,
    domain: String = "",
    interceptors: List<Interceptor>? = null
  ): T {
    val retrofit = Retrofit.Builder()
        .baseUrl(domain)
        .addConverterFactory(CustomGsonConverterFactory.create())
//        .addConverterFactory(GsonConverterFactory.create())
        .client(createClient(interceptors))
        .build()
    return retrofit.create(clazz)
  }

  fun <T> createCoroutineService(
    clazz: Class<T>,
    domain: String = "",
    interceptor: Interceptor
  ): T {
    return createCoroutineService(clazz, domain, mutableListOf(interceptor))
  }

  private fun createClient(interceptors: List<Interceptor>? = null): OkHttpClient {
    val loggerInterceptor = HttpLoggingInterceptor(object : Logger {
      override fun log(message: String) {
        com.demon.logger.Logger.d(TAG, message)
      }
    })
    loggerInterceptor.level = HttpLoggingInterceptor.Level.BODY
    val httpClientBuilder = OkHttpClient.Builder()
    return httpClientBuilder.apply {
      addInterceptor(loggerInterceptor)
    }.apply {
      interceptors?.forEach {
        addInterceptor(it)
      }
    }.apply {
      // TODO 有正式证书需要修改
      unsafeHttpsSettings(this)
    }.build()
  }

  private fun unsafeHttpsSettings(builder: OkHttpClient.Builder): OkHttpClient.Builder {
    return builder.sslSocketFactory(getSSlFactory(), object : X509TrustManager {
      override fun checkClientTrusted(
        chain: Array<out X509Certificate>?,
        authType: String?
      ) {
      }

      override fun checkServerTrusted(
        chain: Array<out X509Certificate>?,
        authType: String?
      ) {
      }

      override fun getAcceptedIssuers(): Array<X509Certificate> {
        return emptyArray()
      }
    }).hostnameVerifier(CustomHostnameVerifier())
  }

  private class CustomHostnameVerifier : HostnameVerifier {
    override fun verify(
      hostname: String?,
      session: SSLSession?
    ): Boolean {
      return true
    }

  }

  private fun getSSlFactory(): SSLSocketFactory {
    val trustAllCerts: Array<TrustManager> = arrayOf<TrustManager>(
        object : X509TrustManager {
          override fun checkClientTrusted(
            chain: Array<out X509Certificate>?,
            authType: String?
          ) {
          }

          override fun checkServerTrusted(
            chain: Array<out X509Certificate>?,
            authType: String?
          ) {
          }

          override fun getAcceptedIssuers(): Array<X509Certificate> {
            return emptyArray()
          }
        }
    )
    // Install the all-trusting trust manager
    // Install the all-trusting trust manager
    val sslContext: SSLContext = SSLContext.getInstance("SSL")
    sslContext.init(null, trustAllCerts, SecureRandom())
    // Create an ssl socket factory with our all-trusting manager
    // Create an ssl socket factory with our all-trusting manager
    return sslContext.socketFactory

  }
}